home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PCMania 36
/
PCMania CD36_1.iso
/
pcmania
/
c36
/
ascpov2.c
< prev
Wrap
C/C++ Source or Header
|
1980-03-14
|
18KB
|
607 lines
#include <stdio.h>
#include <math.h>
#include <dos.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
unsigned int searchtext(unsigned char *, unsigned char *,
unsigned int, FILE *);
unsigned int sigword(unsigned char *, unsigned int);
unsigned int tomanombre(unsigned char *, unsigned char *, unsigned int);
unsigned int tomanom_s(unsigned char *, unsigned char *, unsigned int);
void retocapov(void);
void cargar(FILE *);
void normalp(unsigned int);
#define maxlon 12192
#define razonC 35.2044 /* constante para conversion de la camara */
unsigned char bufferR[maxlon]; /* buffer para datos de F. a leer */
double vertices[19000][3]; /* reservar espacio para un max. de 19000 vertices */
double normal[38000][3]; /* las normales de un max. de 38000 caras */
unsigned int caras[38000][3];/* ind. los vertices de cada cara (para un
calculo rapido de las normales de los vert.) */
FILE *fichasc; /* handle para fichero .asc a leer */
FILE *fichpov; /* handle para fichero .pov a escribir */
FILE *fichinc; /* handle para fichero .inc a escribir */
unsigned int posr; /* pos. relativa dentro del buffer */
unsigned char string[50]; /* cadenas de trabajo */
unsigned char string1[50];
unsigned char nombref[30];
unsigned char mam[30];
unsigned char mam1[30];
unsigned char textur[30];
unsigned char libtex[60][30]; /* libreria de texturas (max. 60) */
int primtex; /* indica prim. zona libre de libtext */
double xi,yi,zi,xf,yf,zf; /* valores intermedios para calculo de normales */
unsigned nvertices,nfaces; /* num. de vertices y caras de objeto en curso */
main()
{
long a,b,c;
char d;
double pella;
int nobj;
double v0,v1,v2; /* valores de comparacion de triangulos degen. */
nobj=0;
posr=0;
primtex=0;
/* scr_setmode(3); */
puts(" Ascpov 0.9 por Jose Manuel Muñoz Perez\n");
/* exec("\\command.com", "/cdir /w *.asc"); */
system("dir /w *.asc"); /* sustituye a la linea anterior */
printf("indica el fichero 3dstudio (ASC) a tratar ");
scanf("%s",mam);
strcpy(string,mam);
strcat(string,".asc");
if ((fichasc=fopen(string,"r"))==0)
{
printf("\n Error: El fichero no puede abrirse!\n\n");
exit(1);
}
strcpy(string,mam);
strcpy(nombref,string); /* preservar nombre del F. */
strcat(string,".inc");
strcpy(string1,string); /* preservar nombre.inc */
if ((fichinc=fopen(string,"w"))==0)
{
printf("\n Error: El fichero no puede crearse!\n\n");
exit(1);
}
strcpy(string,mam);
strcat(string,".pov");
if ((fichpov=fopen(string,"w"))==0)
{
printf("\n Error: El fichero no puede crearse!\n\n");
exit(1);
}
cargar(fichasc); /* cargar 70 lineas del f. */
posr=0;
/* poner includes basicos */
fputs("#include \"colors.inc\"\n",fichpov);
fputs("#include \"textures.inc\"\n",fichpov);
/* buscar objeto */
buscaobj:
nobj++;
posr=searchtext(bufferR,"Named object:",posr,fichasc);
if (posr==65535)
{
retocapov(); /* poner texturas de objetos y nombres de
estos en la union final */
fclose(fichasc);
fclose(fichpov);
fclose(fichinc);
exit(0);
}
posr=sigword(bufferR,posr); /* nos posicionamos sobre el nombre del objeto */
posr++; /* nos saltamos las comillas del nombre */
posr=tomanombre(bufferR,mam,posr);
/* metemos el nombre del objeto en 'mam' */
a=strlen(mam);
mam[a-1]=0; /* quitamos las comillas del nombre poniendo
un 0 (fin de cadena, ¿recuerdan?) */
posr=sigword(bufferR,posr); /* nos posicionamos sobre la siguiente palabra
(el tipo de objeto; Camera, Direct light, Tri-mesh (objeto)) */
posr=tomanom_s(bufferR,mam1,posr);
printf("currando sobre objeto ");
printf("%s\n",mam);
/* ya tenemos el tipo de objeto en mam1[] */
if (!strcmp(mam1,"Camera"))
{
/* primero nos posicionamos sobre la "lente" de la camara */
posr=sigword(bufferR,posr);
posr++;
pella=atof(bufferR+posr);
pella/=razonC; /* calculado el "Zoom" de la camara */
fputs("camera {\n location <",fichpov);
posr-=10;
posr=searchtext(bufferR,"Position:",posr,fichasc);
posr=sigword(bufferR,posr);
posr+=2; /* con esto estamos posicionados sobre la X */
posr=tomanom_s(bufferR,mam1,posr);
fputs(mam1,fichpov);
fputs(", ",fichpov);
posr+=3;
posr=tomanom_s(bufferR,mam1,posr);
fputs(mam1,fichpov);
fputs(", ",fichpov);
posr+=3;
posr=tomanom_s(bufferR,mam1,posr);
fputs(mam1,fichpov);
fputs(">\n",fichpov);
fputs(" direction <0.0, ",fichpov);
fprintf(fichpov,"%f",pella);
fputs(", 0.0>\n up <0.0, 0.0, 1.0>\n",fichpov);
fputs(" sky <0, 0, 1>\n",fichpov);
fputs(" right <1.33,0.0, 0.0>\n look_at <",fichpov);
posr=searchtext(bufferR,"X:",posr,fichasc);
/* esta X correponde a Target (punto al que apunta la camara) */
posr=tomanom_s(bufferR,mam1,posr);
fputs(mam1,fichpov);
fputs(", ",fichpov);
posr+=3;
posr=tomanom_s(bufferR,mam1,posr);
fputs(mam1,fichpov);
fputs(", ",fichpov);
posr+=3;
posr=tomanom_s(bufferR,mam1,posr);
fputs(mam1,fichpov);
fputs(">\n}\n\n",fichpov);
}
else if (!strcmp(mam1,"Direct"))
{ /* por "Direct light" */
fputs("light_source {<",fichpov);
posr=searchtext(bufferR,"X:",posr,fichasc);
/* la primera "X:" corresponde a la "Position" de la luz (consultar
el fichero .asc) */
posr=tomanom_s(bufferR,mam1,posr);
fputs(mam1,fichpov);
fputs(", ",fichpov);
posr+=3;
posr=tomanom_s(bufferR,mam1,posr);
fputs(mam1,fichpov);
fputs(", ",fichpov);
posr+=3;
posr=tomanom_s(bufferR,mam1,posr);
fputs(mam1,fichpov);
fputs(">\n color rgb <",fichpov);
posr=searchtext(bufferR,"Red=",posr,fichasc);
/* esto esta dentro de la orden "Light color" del fichero .asc */
posr=tomanom_s(bufferR,mam1,posr);
fputs(mam1,fichpov); /* componente rojo de la luz */
fputs(", ",fichpov);
posr=searchtext(bufferR,"Green=",posr,fichasc);
posr=tomanom_s(bufferR,mam1,posr);
fputs(mam1,fichpov); /* componente verde */
fputs(", ",fichpov);
posr=searchtext(bufferR,"Blue=",posr,fichasc);
posr=tomanom_s(bufferR,mam1,posr);
fputs(mam1,fichpov); /* componente azul */
fputs(">\n}\n\n",fichpov);
}
else if (!strcmp(mam1,"Tri-mesh,"))
{
fputs("#declare ",fichinc);
fputs(mam,fichinc);
fputs("=union{\n",fichinc);
posr=searchtext(bufferR,"Vertices:",posr,fichasc);
posr++; /* saltar espacio en blanco */
nvertices=atoi(bufferR+posr);
posr=searchtext(bufferR,"Faces:",posr,fichasc);
posr++; /* saltar espacio en blanco */
nfaces=atoi(bufferR+posr);
/* ahora tomar los vertices. Primero nos situamos en el primero -el 0 */
posr=searchtext(bufferR,"Vertex 0:",posr,fichasc);
for (a=0;a<nvertices;a++)
{
posr=searchtext(bufferR,"X:",posr,fichasc);
pella=atof(bufferR+posr);
vertices[a][0]=pella;
posr=searchtext(bufferR,"Y:",posr,fichasc);
pella=atof(bufferR+posr);
vertices[a][1]=pella;
posr=searchtext(bufferR,"Z:",posr,fichasc);
pella=atof(bufferR+posr); /* esto es por si el atof() de PCC da problems */
vertices[a][2]=pella;
}
/* ahora tomaremos los datos de la lista de caras */
posr=searchtext(bufferR,"Face list:",posr,fichasc);
for (a=0;a<nfaces;a++)
{
posr=searchtext(bufferR,"Face ",posr,fichasc);
posr=searchtext(bufferR," A:",posr,fichasc);
caras[a][0]=atoi(bufferR+posr); /* tomar 1er vertice del triangulo */
posr=searchtext(bufferR," B:",posr,fichasc);
caras[a][1]=atoi(bufferR+posr); /* tomar 2ndo vertice del triangulo */
posr=searchtext(bufferR," C:",posr,fichasc);
caras[a][2]=atoi(bufferR+posr); /* tomar 3er vertice del triangulo */
if (a==0) /* tomar nombre de textura (si lo hay) */
{
/* primero buscar primer caracter de las palabras "Material", "Smoothing"
o "Face", (Material es que el objeto tiene una textura, Smoothing que
carece de ella, pero el objeto tiene un contorno suavizado) */
while(bufferR[posr]!='M' && bufferR[posr]!='S' &&
bufferR[posr]!='F' && bufferR[posr]!=255)
posr++;
if (bufferR[posr]==255)
{ /* ultima linea de carga anterior */
cargar(fichasc); /* leer otra tanda de lineas */
posr=0;
}
else if (bufferR[posr]=='F')
{
strcpy(textur,"defecto");
continue;
}
else if (bufferR[posr]=='M')
{
posr+=10; /* posicionarnos sobre el nombre de la text. */
c=0;
while(bufferR[posr]!='"')
{
/* las dos lin. sigs. estan porque el nombre de textura puede tener
espacios dentro (por eso no empleamos tomanombre() ¡¡@#⌠⌡AG!! */
if (bufferR[posr]==32)
mam1[c]='_';
else
mam1[c]=bufferR[posr];
c++;
posr++;
}
mam1[c]=0;
strcpy(textur,mam1); /* ya tenemos en textur[] el nombre de text. */
}
else
strcpy(textur,"defecto");
/* finalmente miramos si la textura esta o no en la lista de nombres de
texturas */
for (c=0;c<primtex;c++)
{
if (!strcmp(textur,libtex[c]))
goto salirtex; /* si, ya se que los puristas pediran mi sangre
por esta linea... */
}
strcpy(libtex[primtex],textur);
primtex++; /* apuntar a prox. nombre de text. libre */
}
salirtex:
continue;
}
/* ahora crear tabla normal[], donde guardaremos las normales calculadas
de cada poligono */
for (a=0;a<nfaces;a++)
{
xi=vertices[caras[a][1]][0] - vertices[caras[a][0]][0];
yi=vertices[caras[a][1]][1] - vertices[caras[a][0]][1];
zi=vertices[caras[a][1]][2] - vertices[caras[a][0]][2];
xf=vertices[caras[a][2]][0] - vertices[caras[a][0]][0];
yf=vertices[caras[a][2]][1] - vertices[caras[a][0]][1];
zf=vertices[caras[a][2]][2] - vertices[caras[a][0]][2];
normal[a][0]= (yi*zf) - (zi*yf); /* X */
normal[a][1]= (zi*xf) - (xi*zf); /* Y */
normal[a][2]= (xi*yf) - (yi*xf); /* Z */
}
/* ahora escribir cada smooth_triangle. Para cada vertice hay que hacer un
bucle de busqueda en caras[] para ver en cuantas de las caras del objeto
interviene dicho vertice. (La normal de cada vertice se calcula con el
promedio de las normales de las caras que emplean el susodicho vertice). */
for (a=0;a<nfaces;a++)
{
/* antes que nada, comprobar si el triangulo es degenerado. v0 es la suma de
los val. X,Y,Z del vertice 0, v1 la suma del vertice 2 e idem. para v2 */
v0=vertices[caras[a][0]][0]+vertices[caras[a][0]][1]+
vertices[caras[a][0]][2];
v1=vertices[caras[a][1]][0]+vertices[caras[a][1]][1]+
vertices[caras[a][1]][2];
v2=vertices[caras[a][2]][0]+vertices[caras[a][2]][1]+
vertices[caras[a][2]][2];
if (v0==v1 || v0==v2 || v1==v2)
continue; /* desechamos este triangulo */
else
{
fputs(" smooth_triangle{\n <",fichinc);
fprintf(fichinc,"%f",vertices[caras[a][0]][0]);
fputs(", ",fichinc);
fprintf(fichinc,"%f",vertices[caras[a][0]][1]);
fputs(", ",fichinc);
fprintf(fichinc,"%f",vertices[caras[a][0]][2]);
fputs("> <",fichinc);
normalp(caras[a][0]); /* calcular la normal promediada del vertice 0 */
/* los valores devueltos estan en xi, yi y zi */
fprintf(fichinc,"%f",xi);
fputs(", ",fichinc);
fprintf(fichinc,"%f",yi);
fputs(", ",fichinc);
fprintf(fichinc,"%f",zi);
fputs(">\n <",fichinc);
/* ahora el vertice 1 */
fprintf(fichinc,"%f",vertices[caras[a][1]][0]);
fputs(", ",fichinc);
fprintf(fichinc,"%f",vertices[caras[a][1]][1]);
fputs(", ",fichinc);
fprintf(fichinc,"%f",vertices[caras[a][1]][2]);
fputs("> <",fichinc);
normalp(caras[a][1]); /* calcular la normal promediada del vertice 1 */
fprintf(fichinc,"%f",xi);
fputs(", ",fichinc);
fprintf(fichinc,"%f",yi);
fputs(", ",fichinc);
fprintf(fichinc,"%f",zi);
fputs(">\n <",fichinc);
/* ahora el vertice 2 */
fprintf(fichinc,"%f",vertices[caras[a][2]][0]);
fputs(", ",fichinc);
fprintf(fichinc,"%f",vertices[caras[a][2]][1]);
fputs(", ",fichinc);
fprintf(fichinc,"%f",vertices[caras[a][2]][2]);
fputs("> <",fichinc);
normalp(caras[a][2]); /* calcular la normal promediada del vertice 2 */
fprintf(fichinc,"%f",xi);
fputs(", ",fichinc);
fprintf(fichinc,"%f",yi);
fputs(", ",fichinc);
fprintf(fichinc,"%f",zi);
fputs(">}\n",fichinc);
}
}
fputs("texture {",fichinc);
fputs(textur,fichinc);
fputs("}\n}\n",fichinc);
}
goto buscaobj;
}
/* Esta funcion busca una cadena de texto dentro de un array de caracteres.
Devuelve 65535 si no lo ha hallado o un valor entero indicando su pos.
en dicho array. La funcion acepta como parametros un puntero a la cadena
donde va a efectuarse la busqueda, otro puntero a la cadena que se va a
buscar y un indice al punto de principio para la busqueda (puede ser
preciso que la investigacion no comienze desde el principio).
Cuando una ocurrencia sobrepase las ultimas lineas de la carga anterior
se leera otra tanda de lineas (por ello tambien adjuntamos el puntero
*FILE al fichero que deseamos leer). logicamente en ese caso el indice
a devolver continuara la busqueda desde 0 */
unsigned int searchtext(unsigned char *buffer, unsigned char *text,
unsigned int desp, FILE *fich)
{
long a,b,c;
unsigned char loncad;
int d;
a=0;
loncad=strlen(text);
sigcar:
while(buffer[desp]!=text[a] && buffer[desp]!=255 && buffer[desp]!=0)
desp++;
if (buffer[desp]==255)
{
cargar(fich); /* leer mas lineas */
desp=0;
goto sigcar;
}
if (buffer[desp]==0)
return(65535); /* marca de que no se ha hallado correspondencia */
/* si llega aqui, es que se ha leido el car. */
d=desp;
for (b=0,c=desp;b<loncad-1;a++,b++,c++)
{
if (buffer[c]!=text[a])
{
a=0;
desp++;
goto sigcar;
}
}
a=d+loncad;
return (a);
/* a=d+loncad es porque el indice devuelto corresponde a la primera pos.
del array, despues de la ocurrencia hallada */
}
/* llamamos a sigword() cuando deseamos hallar el indice dentro del array
a la sig. palabra que sigue a la ultima procesada (indicada por desp) */
unsigned int sigword(unsigned char *buffer, unsigned int desp)
{
/* primero nos saltamos los car. de la palabra actual */
while(buffer[desp]!=32 && buffer[desp]!=13 &&
buffer[desp]!=10 && buffer[desp]!=255)
desp++;
if (bufferR[desp]==255)
{ /* ultima linea de carga anterior */
cargar(fichasc); /* leer otra tanda de lineas */
desp=0;
}
/* y ahora los espacios hasta la siguiente palabra */
while((buffer[desp]==32 || buffer[desp]==13 || buffer[desp]==10) &&
buffer[desp]!=255)
desp++;
if (bufferR[desp]==255)
{
cargar(fichasc);
desp=0;
}
return desp;
}
/* toma el nombre alterando algunos caracteres que no permite el POV */
unsigned int tomanombre(unsigned char *buffer,
unsigned char *text, unsigned int desp)
{
unsigned char a;
a=0;
while(buffer[desp]!=32 && buffer[desp]!=13 && buffer[desp]!=10)
{
if ((buffer[desp]>=48 && buffer[desp]<=57) || buffer[desp]=='"' ||
(buffer[desp]>=65 && buffer[desp]<=90) ||
(buffer[desp]>=97 && buffer[desp]<=122))
text[a]=buffer[desp]; /* es uno de los car. permitidos por POV */
else
text[a]='_';
a++;
desp++;
}
text[a]=0; /* marca para fin de cadena */
return desp;
}
/* toma el nombre sin alteraciones */
unsigned int tomanom_s(unsigned char *buffer,
unsigned char *text, unsigned int desp)
{
unsigned char a;
a=0;
while(buffer[desp]!=32 && buffer[desp]!=13 && buffer[desp]!=10)
{
text[a]=buffer[desp];
a++;
desp++;
}
text[a]=0; /* marca para fin de cadena */
return desp;
}
/* Pone las plantillas para las texturas y los nombres de los objetos en la
"union" del fichero.pov */
void retocapov(void)
{
unsigned int a,b;
int d;
puts("ajustando fichero .pov");
fclose(fichinc);
for(b=0;b<primtex;b++)
{
fputs("#declare ",fichpov);
fputs(libtex[b],fichpov);
fputs("= texture{\n pigment {White}\n",fichpov);
fputs(" finish {\n specular 1\n roughness 0.001\n }\n}\n\n",fichpov);
}
fputs("#include \"",fichpov);
fputs(string1,fichpov);
fputs("\"\n\n",fichpov);
/* abrimos nuevamente el fichero, para reinicializar el indicador de
posicion de archivo. Naturalmente, en vez de esto podriamos haber usado
fseek() */
if ((fichinc=fopen(string1,"r"))==0)
{
printf("\n Error: El fichero no puede abrirse!\n\n");
exit(1);
}
cargar(fichinc); /* cargar 70 lineas del f. */
posr=0;
/* ahora incluimos en el f. pov la lista de objetos definidos en el F.
.inc. Por supuesto esto puede ser retoc. por el usuario */
fputs("// lista de objetos de la escena\n\n ",fichpov);
for(;;)
{
posr=searchtext(bufferR,"declare",posr,fichinc);
if (posr==65535)
return;
posr=sigword(bufferR,posr);
posr=tomanom_s(bufferR,string,posr);
a=0;
while(string[a]!='=')
a++;
string[a]=0;
fputs(string,fichpov);
fputs("\n ",fichpov);
}
}
/* ahora leer 80 lineas como maximo a partir de bufferR+0 */
void cargar(FILE *fich)
{
unsigned int a,b,c;
int d;
for (a=0,b=80;b!=0;b--)
{
d=fgets(bufferR+a,512,fich);
if (d!=0)
{
while (bufferR[a]!=0)
a++;
}
else
return;
}
if (d!=0)
bufferR[a]=255; /* marca de ultima de las 70 lineas */
}
/* calcular la normal promediada del vertice */
void normalp(unsigned int vert)
{
unsigned int a,b;
xi=0;
yi=0;
zi=0;
b=0; /* num. de caras de las que forma parte el vertice */
for (a=0;a<nfaces;a++)
{
if (vert==caras[a][0] || vert==caras[a][1] || vert==caras[a][2])
{
b++; /* el vertice forma parte de esta cara */
xi+=normal[a][0];
yi+=normal[a][1];
zi+=normal[a][2];
}
}
xi/=b; /* hallar el promedio */
yi/=b;
zi/=b;
}